﻿/*-------------------------------------------------------------------------
* 命名空间: ScreenCapture.ViewModels/ViewModels
* 类       名: ViewModels
* 功      能:  Exception And Error 的异常处理ViewModel业务处理类
*                 UI和后台的数据交互在这个类中实现
* 时      间:  2023/12/1 15:37:21
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using ScreenCapture.Base;
using ScreenCapture.Common;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Linq;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace ScreenCapture.ViewModels
{
    public class ExceptionViewModel : NotifyPropertyChanged
    {

        /// <summary>
        /// 这个命令是一个响应式编程的一个实现,使得处理异步事件和数据流更加的方便和易读
        /// 这是一个观察者模式去写的语句.
        /// 观察Exceptions对象的Count属性,如果Count大于0,则为True
        /// ToReactiveCommmand(): 这个语句将上述的观察序列转换为一个反应性命令.反应性命令是一个特殊的
        /// 命令,他可以根据其关联的可观察序列的状态自动启用或者是禁用.
        /// WithSubscribe(OnCopyToClipboard)这个语句是订阅命令的执行.当命令生效并且执行的时候,
        /// 它会调用订阅的方法OnCopyToClipboard.
        /// </summary>
        public ExceptionViewModel()
        {
            CopyToClipboardCommand = Exceptions
                .ObserveProperty(M => M.Count)
                .Select(C => C > 0)
                .ToReactiveCommand()
                .WithSubscribe(OnCopyToClipboard);
        }

        // 当复制到粘贴板命令生效的时候调用这个函数(这是一个反应性命令绑定的处理函数)
        private void OnCopyToClipboard()
        {
            var sb = new StringBuilder();
            sb.Append(SystemInfo.GetInfo());
            sb.AppendLine();
            sb.Append(Exceptions[0]);
            sb.ToString().WriteToClipboard();
        }

        private string _message = "发生了一个异常,下面是这个异常的详细信息.";

        public string Message
        {
            get { return _message; }
            set
            {
                Set(ref _message, value);
            }
        }


        // 异常信息列表,为什么要有这个异常信息列表,因为一个异常可能包含有其他的异常(内部异常等)
        public ObservableCollection<Exception> Exceptions { get; } = new ObservableCollection<Exception>();


        private Exception? _selectedException;

        public Exception? SelectedException
        {
            get { return _selectedException; }
            set
            {
                Set(ref _selectedException, value);
            }
        }

        public ICommand? CopyToClipboardCommand { get; }

        /// <summary>
        /// 初始化异常信息的值
        /// </summary>
        /// <param name="Exception"></param>
        /// <param name="Msg"></param>
        public void Init(Exception Exception, string? Msg)
        {
            if (Msg != null)
                Message = Msg;

            while (Exception != null)
            {
                Exceptions.Add(Exception);
                Exception = Exception.InnerException;
            }

            SelectedException = Exceptions[0];
        }
    }
}
